import {onLoad} from "@dcloudio/uni-app"
import {computed, onUnmounted, readonly, ref, watchEffect} from "vue"
import {array, empty, object} from "@/uni_modules/uv-ui-tools/libs/function/test";
import mxConst, {getTabRoutes} from "@/common/mxConst";
import {guid} from "@/uni_modules/uv-ui-tools/libs/function";

export const useTransfer = function () {
    // data
    const cacheKey = ref('')
    const prevData = ref({})
    const usingCacheTransfer = computed(() => !!cacheKey.value)

    // hooks
    onLoad((opt) => {
        if (opt.cacheKey) cacheKey.value = opt.cacheKey, prevData.value = uni.getStorageSync(opt.cacheKey)
        else prevData.value = JSON.parse(decodeURIComponent(opt.data || '{}'))
    })
    onUnmounted(() => {
        if (usingCacheTransfer.value) {
            uni.removeStorageSync(cacheKey.value)
        }
    })

    // methods

    /*
    * tool function for pickup indicates props from source
    * @param {Array} propsArray - indicates props array
    * @param {Array} sourceArray - pick values from source array
    * @return {Object} - picked object
    * */
    const pickUpObject = function (propsArray, sourceArray) {
        const obj = {}
        sourceArray.forEach(item => {
            if (empty(item)) return
            propsArray.forEach(prop => {
                if (Object.hasOwnProperty.call(item, prop)) {
                    obj[prop] = item[prop]
                }
            })
        })
        return obj
    }

    /*
    * main function for route, it keeps params type and supports big data transfer
    * @param {String|Object} urlOrOptions - route url or options
    * @param {Object} props - indicates props to pickup from source data
    * @param {Array} source - source data array, default is [prevData.value]
    * @param {Boolean} usingCache - whether to use cache, default is false, for big data transfer
    * */
    const transferTo = function (urlOrOptions, props = {}, source = null, usingCache = false) {
        const options = object(urlOrOptions) ? urlOrOptions
            : {url: urlOrOptions, type: getTabRoutes().includes(urlOrOptions) ? 'tab' : 'to'}

        // confirm params
        let params = options.params || {}
        let extra = {}
        const extraSource = [prevData.value].concat(source)
        if (array(props)) extra = pickUpObject(props, extraSource)
        else if (object(props)) extra = uni.$uv.deepMerge(props, pickUpObject(Object.keys(props), extraSource))
        params = uni.$uv.deepMerge(params, extra)

        // handle params, using JSON.stringify or uni.setStorageSync
        let formatParams = params
        if (!empty(params)) {
            if (usingCache) {
                const storageKey = mxConst.keyCacheUniquePrefix + guid()
                uni.setStorageSync(storageKey, params)
                formatParams = {cacheKey: storageKey}
            } else {
                formatParams = {data: encodeURIComponent(JSON.stringify(params))}
            }
        }

        // 这里并没有干涉其它参数，所以$uv.route支持的功能这里应该都能用
        options.params = formatParams
        uni.$uv.route(options)
        console.log('transferTo:', options, params)
    }

    /*
    * tool function for clean all transfer cache data,
    * 这里提供了一个清除所有缓存数据的工具函数，
    * 可以用在一些管理性功能页中，如果页面非正常中断可能会累积一些缓存，
    * 这个函数可以用来清除所有缓存数据。
    * 注意：这个函数只是清除 transferTo 中 usingCache=true 产生缓存数据.
    * */
    const cleanAllTransferCacheData = function () {
        // 根据mxConst.keyCacheUniquePrefix清除所有缓存
        // 提供给某些管理性功能页使用，如果页面非正常中断可能会累积一些缓存
        const keys = uni.getStorageInfoSync().keys
        keys.forEach(key => {
            if (key.startsWith(mxConst.keyCacheUniquePrefix))
                uni.removeStorageSync(key)
        })
    }

    return {
        cacheKey: readonly(cacheKey), // 安全考虑，不允许外部修改
        prevData,
        usingCacheTransfer,
        pickUpObject,
        transferTo,
        cleanAllTransferCacheData
    }
}
